local nl = require'luaNumeric'
require 'luaFDTD3D'
local plot = require "Q2DViewerEx"

----------------------------------------------------------------------------------------------------------------------------------------
--初始化参数
local LumpedSrcPost={
	funs = {};
	xAxis = 0;
	ytype = 1;
	xtype = 1;
	is_voltages = false;
	is_currents = false;
	is_sparameters = true;
	is_impendences = false;
	is_power = false;
};
----------------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------------------
--创建表和创建元表
function LumpedSrcPost:new (o)
	o = o or {};
	self.__index = self;
	setmetatable(o,self)
	o:init();
	return o;
end
----------------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------------------
--更新参数
function LumpedSrcPost:change_is_voltages (s)
	if self.is_voltages ~= s then
		self.is_voltages = s;
		self:plot();
	end
end
function LumpedSrcPost:change_is_currents (s)
	if self.is_currents ~= s then
		self.is_currents = s;
		self:plot();
	end
end
function LumpedSrcPost:change_is_impendances (s)
	if self.is_impendances ~= s then
		self.is_impendances = s;
		self:plot();
	end
end
function LumpedSrcPost:change_is_sparameters (s)
	if self.is_sparameters ~= s then
		self.is_sparameters = s;
		self:plot();
	end
end
function LumpedSrcPost:change_is_power (s)
	if self.is_power ~= s then
		self.is_power = s;
		self:plot();
	end
end
----------------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------------------
--创建表和创建元表
function LumpedSrcPost:init ()
	self.funs = {};
	self.funs.abs = function(input) return nl.abs(input); end;
	self.funs.phs = function(input) return nl.arg(input)*180/pi; end;
	self.funs.real = function(input) return nl.real(input); end;
	self.funs.imag = function(input) return nl.imag(input); end;
	self.funs.log = function(input) 
		local  d = nl.abs(input);		
		for k,v in pairs(d) do 
			if d[k] < 1e-200 then d[k] = 1e-200; end
		end
		d = 20* nl.log10(d)
		return d; 
	end;
	self.fun_names = {};
	self.fun_names[1] = 'log';
	self.fun_names[2] = 'abs';
	self.fun_names[3] = 'phs';
	self.fun_names[4] = 'real';
	self.fun_names[5] = 'imag';	
	self.ytype = 1;
end
----------------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------------------
--更新数据
function LumpedSrcPost:refresh_figs ()
	self.probe:update();
	self.results = self.probe:results();
	self:plot()
end
----------------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------------------
--画图
function LumpedSrcPost:plot ()
	self.view:clearGraphs();
	local x = self.results.freq;
	if self.xtype ==2 then
		x = self.results.lambda;
	end
	local fun = self.funs[ self.fun_names[self.ytype] ];
	assert( self.results.data['Sout'], '数据不存在！' );
	
	--self.view:addGraph(x,  fun( self.results.data['Pout (w)'] ), 'Pout' );
	--self.view:addGraph(x,  fun( self.results.data['PTotal (w)'] ), 'Pout' );
	local sout =nl.abs( self.results.data['Sout'] );
	local pout =nl.abs( self.results.data['Pout (w)'] );
	local UU =self.results.data['voltage (V)']; --50欧姆上的电压
	local II =self.results.data['current (A)']; --电流
	local Imp = self.results.data['impedance (omega)'] ; --电流
	
	local psrc = self:get_src_power();
	if self.is_voltages == true then
		self.view:addGraph(x,  fun( UU/psrc ), 'voltages' );
		--self.view:addGraph(x,  fun( psrc ), 'power' );
	end
	
	if self.is_currents == true then
		self.view:addGraph(x,  fun( II/psrc ), 'currents' );
	end	
	if self.is_impendances == true then
		self.view:addGraph(x,  fun( Imp ), 'impedances' );
	end	
	
	if self.is_power == true then
		self.view:addGraph(x,  fun( UU/psrc*UU/psrc/50/50  ), 'power' );
	end
		
	--self.view:addGraph(x,  fun( self.results.data['Sout'] ), 'S11' );
	--self.view:addGraph(x,  fun( s11 ), 'S11-1' );

	if self.probe:shape_type()=='LumpedSrc'  and self.is_sparameters == true then
		if self.probe:amplitude() > 1e-3 then 
			self.view:addGraph(x,  fun( self.results.data['Sout'] ), 'S['..self.probe:name()..']_[' .. self.probe:name() ..']'  );
		end
		local data = self.results.data['voltage (V)'];
		local freq = self.results.freq;
		local objs = Geometry.get_all_objects('','source');
		for k,v in pairs (objs) do 
			if v:shape_type()=='LumpedSrc' then
				if v:name() ~= self.probe:name() and v:amplitude() > 1e-3 then 
					local res = v:results();
					local vfreq = res.freq;
					local vptotal = nl.sqrt( nl.abs(res.data['PTotal (w)'])  * 50)
					data_s = nl.new_cvector(#freq);
					for ii=1,#freq do 
						ptotal = nl.interpolation(vfreq,vptotal,freq[ii]);
						data_s[ii] = data[ii]/ptotal;
					end
					self.view:addGraph(x,  fun( data_s ), 'S['..v:name()..']_[' .. self.probe:name() ..']' );
				end

			end
		end
	end

	self.view:rescaleAxes();
	self:set_axis();
end
----------------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------------------
--获得所有集总源的功率
function LumpedSrcPost:get_src_power ()
	local freq = self.results.freq;
	local 	data_s = nl.new_cvector(#freq);
	for kk,vv in pairs(data_s) do 
		data_s[kk] = 0 ;
	end
	local nlumpedsrc = 0;
	local objs = Geometry.get_all_objects('','source');
	for k,v in pairs (objs) do 
		if v:shape_type()=='LumpedSrc' then
			if v:amplitude() > 1e-3 then 
				local res = v:results();
				local vfreq = res.freq;
				local vptotal = nl.abs(res.data['PTotal (w)'])
				for ii=1,#freq do 
					ptotal = nl.interpolation(vfreq,vptotal,freq[ii]);
					data_s[ii] = data_s[ii]+ptotal;
				end
				nlumpedsrc = nlumpedsrc + 1;
			end
		end
	end
	if nlumpedsrc==0 then 
		for kk,vv in pairs(data_s) do 
			data_s[kk] = 1 ;
		end
	end
	return nl.sqrt(data_s);
end
----------------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------------------
--画图
function LumpedSrcPost:rescale ()
	self:update_parameters_from_ui();
	self:plot();
end
----------------------------------------------------------------------------------------------------------------------------------------

function LumpedSrcPost:get_yaxis_lable()
	local str = '';
	if self.ytype ==1 then
		str =" [dB]"
	elseif self.ytype ==2 then
		str =" [Mag.]"
	elseif self.ytype ==3 then
		str =" [Argument]"
	elseif self.ytype ==4 then
		str =" [Real part]"
	elseif self.ytype ==5 then
		str =" [Imag part]"
	end
	return str;
end
----------------------------------------------------------------------------------------------------------------------------------------
--坐标设置
function LumpedSrcPost:set_axis()
	if self.xtype ==2 then
		self.view.xAxis:setProperty( {name="波长 ["..Geometry.ref_units_dim_str()..']'} )
	else
		self.view.xAxis:setProperty( {name="频率 ["..Geometry.ref_units_freq_str()..']'} )
	end
	
	if self.ytype ==1 then
		self.view.yAxis:setProperty( {name="Y [dB]"} )
	elseif self.ytype ==2 then
		self.view.yAxis:setProperty( {name="Y [Mag.]"} )
	elseif self.ytype ==3 then
		self.view.yAxis:setProperty( {name="Argument of Y [arc.]"} )
	elseif self.ytype ==4 then
		self.view.yAxis:setProperty( {name="Real part of Y"} )
	elseif self.ytype ==5 then
		self.view.yAxis:setProperty( {name="Imag part of Y"} )
	end
	 self.view:rescaleAxes();
end
----------------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------------------
--导出
function LumpedSrcPost:export_data (path)
	print(path);
	self.probe:save(path);
end
----------------------------------------------------------------------------------------------------------------------------------------


--===========================================================================--
--格式化数据
function LumpedSrcPost:get_data()
	local header = nl.new_svector();
	header:add('Index')
	header:add('Frequency('..Geometry.ref_units_freq_str()..')')
	header:add('Lambda('.. Geometry.ref_units_dim_str() ..')')
	local fun = self.funs[ self.fun_names[self.ytype] ];

	--for ifreq = 1,#self.results.freq do  	
	local ncols = 3;
	if self.is_sparameters == true then
		header:add( 'S11' .. self:get_yaxis_lable() )
		ncols = ncols + 1;
	end
	if self.is_voltages == true then
		header:add( 'Voltages' .. self:get_yaxis_lable() )
		ncols = ncols + 1;
	end
	if self.is_currents == true then
		header:add( 'Currents' .. self:get_yaxis_lable() )
		ncols = ncols + 1;
	end
	if self.is_impendances == true then
		header:add( 'Impedances' .. self:get_yaxis_lable() )
		ncols = ncols + 1;
	end
	--end
	local sout =fun( self.results.data['Sout'] ) ;
	local UU = fun(self.results.data['voltage (V)'] ); --50欧姆上的电压
	local II = fun(self.results.data['current (A)'] ); --电流
	local Imp = fun( self.results.data['impedance (omega)']  ); --电流
	
	local data = nl.new_eigen_smatrix(#self.results.freq,ncols)
	for ifreq = 1,#self.results.freq do		
		data[{ifreq,1}] = tostring(ifreq);
		data[{ifreq,2}] = tostring( self.results.freq[ifreq] );
		data[{ifreq,3}] = tostring( self.results.lambda[ifreq] );
		idx = 4;
		if self.is_sparameters == true then
			data[{ifreq,idx}] = tostring( sout[ifreq] );
			idx = idx+1;
		end
		if self.is_voltages == true then
			data[{ifreq,idx}] = tostring( UU[ifreq] );
			idx = idx+1;
		end
		if self.is_currents == true then
			data[{ifreq,idx}] = tostring( II[ifreq] );
			idx = idx+1;
		end
		if self.is_impendances == true then
			data[{ifreq,idx}] = tostring( Imp[ifreq] );
			idx = idx+1;
		end
	end
	return data,header;
end
--===========================================================================--

--===========================================================================--
--查看数据
function LumpedSrcPost:view_data()
	local data,header = self:get_data()
	if data and header then
		self.dataView  = Gallop.DataPost:create_data_table_to_ui();
		self.dataView:set_data(data);
		self.dataView:set_header(header);
	end 
end
--===========================================================================--

return LumpedSrcPost;
